#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <unistd.h>
#include <errno.h>

#ifndef PATH_MAX
#define PATH_MAX 256
#endif

#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 1
#endif

#define DEV_INDEX_TOUCH   0
#define DEV_INDEX_KEYPAD  1

const char *touch_list[] = {"Touchscreen", "TouchScreen", "touch"};
const char *keyboard_list[] = {"keyboard"};

const char *get_nameList_item(int idx, int item)
{
    if(DEV_INDEX_TOUCH == idx) return  touch_list[item];
    if(DEV_INDEX_KEYPAD == idx) return  keyboard_list[item];

    return "UNKNOW";
}

int get_nameList_item_count(int idx)
{
    if(DEV_INDEX_TOUCH == idx) return  3;
    if(DEV_INDEX_KEYPAD == idx) return  1;

    return 0;
}

static int open_device(const char *device, int print_flags, int index, char *out)
{
    int version;
    int fd;
    int clkid = CLOCK_MONOTONIC;
    const char *fmt;
    char name[80];
    char location[80];
    char idstr[80];

    fd = open(device, O_RDWR);
    if(fd < 0) {
        return -1;
    }

    if(ioctl(fd, EVIOCGVERSION, &version)) {
        return -1;
    }

    name[sizeof(name) - 1] = '\0';
    location[sizeof(location) - 1] = '\0';
    idstr[sizeof(idstr) - 1] = '\0';

    if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
        name[0] = '\0';
    }
    if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
        location[0] = '\0';

    }
    if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
        idstr[0] = '\0';
    }

    if (ioctl(fd, EVIOCSCLOCKID, &clkid) != 0) {
        fprintf(stderr, "Can't enable monotonic clock reporting: %s\n", strerror(errno));
    }

    /* find touch event in here, return 1 if not found */
    int count = get_nameList_item_count(index);
    for(int i = 0; i < count; i++) {
        fmt = strstr(name, get_nameList_item(index, i));
        if(fmt) {
            break;
        }
    }

    if(fmt) {
        strncpy(out, device, strlen(device) + 1);
        return 0;
    }
    return 1;
}

/*
 * return 0: find touch screen
 * return 1: don't find touch screen
 *
 */
static int scan_dir(const char *dirname, int index, char *out)
{
    char devname[PATH_MAX];
    char *filename;
    DIR *dir;
    struct dirent *de;
    int ret = 1;

    dir = opendir(dirname);
    if(dir == NULL)
        return -1;
    strcpy(devname, dirname);
    filename = devname + strlen(devname);
    *filename++ = '/';
    while((de = readdir(dir))) {
        if(de->d_name[0] == '.' &&
                (de->d_name[1] == '\0' ||
                 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
            continue;
        strcpy(filename, de->d_name);
        if(0 == open_device(devname, 0x01, index, out)) {
            ret = 0;
            break;
        }
    }
    closedir(dir);
    return ret;
}

const char *find_touch_path(void)
{
    static char touch_path[128];
    memset(touch_path, 0x00, sizeof(touch_path));
    if(scan_dir("/dev/input", DEV_INDEX_TOUCH, touch_path)) {
        return "deviceNotFound";
    }
    return touch_path;
}

const char *find_keyboard_path(void)
{
    static char touch_path[128];
    memset(touch_path, 0x00, sizeof(touch_path));
    if(scan_dir("/dev/input", DEV_INDEX_KEYPAD, touch_path)) {
        return "deviceNotFound";
    }
    return touch_path;
}

